import { isString, pick } from "lodash-es";
import {
  defineComponent,
  Fragment,
  h,
  Ref,
  Teleport,
  unref,
  withDirectives,
} from "vue";
import { ElPagination, ElTable, ElTableColumn, vLoading } from "element-plus";

import { ProForm } from "@/modules/package/form";
import TableBar from "@/modules/package/table/components/TableBar.vue";
import { TProTable } from "@/modules/package/table/components/ProTable.vue";

import useTable from "./useTable";

type UseProTableOptions = {
  size?: "small" | "large";
  showPages?: boolean;
  showTableBar?: boolean;

  fetchUrl: string | Ref<string>;
  fetchOptions?: any;

  formOptions?: {
    col?: any;
    formItems: any[];
  };

  tableOptions: Omit<TProTable, "list" | "loading">;
};

export default function useProTable(options: UseProTableOptions) {
  const {
    size,
    showPages = true,
    fetchUrl,
    fetchOptions,
    tableOptions,
    formOptions,
  } = options || {};

  const {
    refForm,
    list,
    isFetching,
    search,
    pagination,
    submit,
    reset,
    refresh,

    onPageChange,
    onPageSizeChange,

    // execute,
    // bindNodeForPlus,
    // onFetchResponse,
  } = useTable(fetchUrl, fetchOptions);

  const Pagination = defineComponent(
    (props: { to?: string; disabled?: boolean }) => {
      const { to = "#containerFooter" } = props;

      return () =>
        h(
          Teleport,
          { ...props, to },
          h(ElPagination, {
            class: ["p-3"],
            total: pagination.total,
            pageSize: pagination.size,
            currentPage: pagination.page,
            // pageCount: pagination.total,
            background: true,
            layout: "total, prev, pager, next",
            "onUpdate:current-page": onPageChange,
            "onUpdate:page-size": onPageSizeChange,
          })
        );
    },
    {
      props: {
        disabled: Boolean,
        to: String,
      },
    }
  );

  const Table = defineComponent(
    (props) => {
      const { columns } = tableOptions;

      // 处理table列表
      const tableColumns = columns?.map(({ slot, prop, ...item }, index) => {
        const key = slot && isString(slot) ? slot : prop;

        const slotNode =
          (key ? props.colSlots?.[`table-${key}`] : undefined) ?? slot;
        return h(ElTableColumn, { key: key ?? index, prop, ...item }, slotNode);
      });

      return () =>
        withDirectives(
          h(ElTable, { size, stripe: true, data: unref(list) }, tableColumns),
          [[vLoading, unref(isFetching)]]
        );
    },
    { props: { colSlots: Object } }
  );

  const Form = defineComponent(() => {
    const { formItems = [] } = formOptions || {};

    const FormWrap = h("div", { class: "mb-3 bg-white px-4 pt-4 rounded" });

    return () =>
      h(
        FormWrap,
        h(ProForm, {
          ref: (e) => (refForm.value = e),
          size,
          formItems,
          footer: { col: 0 },
          model: unref(search),
          loading: unref(isFetching),
          confirmText: "搜索",
          onSubmit: submit,
          onReset: reset,
        })
      );
  });

  const GridTable = defineComponent((props, { slots }) => {
    const keys = Object.keys(slots);

    const slotToolBar = pick(slots, ["tool-right", "tool-left"]);

    const { formOptions, size, showTableBar = true } = options;

    // 表格控制栏
    const TableBarNode = showTableBar
      ? h(TableBar, { size, onRefresh: refresh }, slotToolBar)
      : null;

    // 展示表单
    const showForm = formOptions?.formItems && formOptions.formItems.length > 0;

    const colSlots = pick(
      slots,
      keys?.filter((e) => e.startsWith("table-"))
    );

    const tableProps = { colSlots };

    const tableWrap = h("div", { class: "bg-white" });
    return () =>
      h(Fragment, [
        showForm ? h(Form) : null,
        h(tableWrap, [
          // 表格操作栏
          TableBarNode ? h(TableBarNode, { loading: isFetching.value }) : null,
          // 表格正文
          h(Table, tableProps),
          showPages ? h(Pagination) : null,
        ]),
      ]);
  });

  return [
    GridTable,
    {
      Pagination,
      tableApi: {
        list,
        isFetching,
        search,
        pagination,
        submit,
        reset,
        refresh,
      },
    },
  ] as const;
}
